package com.autodesk.akn.emr.dao;

import com.amazonaws.ClientConfiguration;
import com.amazonaws.Protocol;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.regions.Region;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.Bucket;
import com.amazonaws.services.s3.model.GetObjectRequest;
import com.amazonaws.services.s3.model.ListObjectsRequest;
import com.amazonaws.services.s3.model.ObjectListing;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectResult;
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.services.s3.model.S3ObjectSummary;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.apache.commons.io.IOUtils;
import org.springframework.stereotype.Repository;

/**
 *
 * @author jeremias.lopez
 */
@Repository
public class S3Dao {

    private AmazonS3Client s3Client;

    public S3Dao(){
         initializeClient();
    }

    private void initializeClient(){
        try {
            Properties prop = new Properties();
            prop.load(S3Dao.class.getClassLoader().getResourceAsStream("config.properties"));
            String accessKey = (String) prop.get("credentials.accessKey");
            String secretKey = (String) prop.get("credentials.secretKey");
            String proxy =(String)prop.get("proxy.enabled");
            boolean proxyneeded = "true".equals(proxy);
            AWSCredentials credentials = new BasicAWSCredentials(accessKey,secretKey);
            s3Client = new AmazonS3Client(credentials);
            //uncomment the following line if you're working through a proxy connection
            if(proxyneeded){
                setProxyConfiguration();
            }
            s3Client.setRegion(Region.getRegion(Regions.US_EAST_1));
        } catch (Exception e){
            e.printStackTrace();
        }
    }

    private void setProxyConfiguration(){
        System.setProperty("com.amazonaws.regions.RegionUtils.fileOverride", "endpoints.xml");
        System.setProperty("https.proxyHost", "proxy.corp.globant.com");
        System.setProperty("https.proxyPort", "3128");
        ClientConfiguration clientConfiguration = new ClientConfiguration();
        clientConfiguration.setProtocol(Protocol.HTTP);
        clientConfiguration.setProxyPort(3128);
        clientConfiguration.setProxyHost("proxy.corp.globant.com");
        s3Client.setConfiguration(clientConfiguration);
    }

    public List<Bucket> listBuckets(){
        return s3Client.listBuckets();
    }

    public PutObjectResult putObject(String filePath, String bucket, String key){
        PutObjectResult res = null;
        try {
            File file = new File(filePath);
            res = s3Client.putObject(bucket,key,file);
        } catch(Exception e){
            e.printStackTrace();
        }
        return res;
    }

    public PutObjectResult putObject(InputStream is, String type, String bucket, String name) {
        PutObjectResult res = null;
        try {
            ObjectMetadata om = new ObjectMetadata();
            om.setContentType(type);
            res = s3Client.putObject(bucket, name, is, om);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return res;
    }

    
    public void deleteObject(String bucket,String key){
        try {
            s3Client.deleteObject(bucket,key);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public ObjectListing listObjects(String bucketName, String prefix, String delimiter){
        ObjectListing res = null;
        try {
            ListObjectsRequest request = new ListObjectsRequest(bucketName, prefix, null, delimiter, null);
            res = s3Client.listObjects(request);
        }catch(Exception e){
            e.printStackTrace();
        }
        return res;
    }

    /**
     *
     * @param bucketName
     * @param key
     * @param os (an output stream from the http response object)
     * @return -1 if failed.
     */
    public int getObject(String bucketName, String key,OutputStream os){
        InputStream is = null;
        int retValue = -1;
        try {
            S3Object object = s3Client.getObject(new GetObjectRequest(bucketName, key));
            is = object.getObjectContent();
            if(is != null){
                retValue = IOUtils.copy(is,os);
            }
        } catch (Exception e){
            e.printStackTrace();
        } finally {
            try {
                if(is!=null){
                    is.close();
                }
                os.close();
            }catch (IOException e){
                e.printStackTrace();
            }
        }
        return retValue;
    }

    public InputStream getObject(String bucketName, String key){
        InputStream is = null;
        S3Object object = s3Client.getObject(new GetObjectRequest(bucketName, key));
        is = object.getObjectContent();
        return is;
    }

    public Bucket createBucket(String bucketName, String region){
        Bucket createdBucket = null;
        try{
            createdBucket = s3Client.createBucket(bucketName,region);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return createdBucket;
    }

    public void deleteBucket(String bucketName){
        try{
            s3Client.deleteBucket(bucketName);
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    public List<String> listSavFiles(String bucketName, String prefix){
        List<String> files = null;

        try{
            files = new ArrayList<String>();

            ObjectListing result = this.listObjects(bucketName,prefix,"/");

            if(result!=null && result.getObjectSummaries()!=null){
                List<S3ObjectSummary> fileList = result.getObjectSummaries();
                for(S3ObjectSummary summary : fileList){
                    if(!summary.getKey().contains(".sav")){
                        continue;
                    }
                    files.add(extractFileNameFromPath(summary.getKey()));
                }
            }
        } catch(Exception e) {
            e.printStackTrace();
        }

        return files;
    }

    public List<String> listCsvFiles(String bucketName, String prefix){
        List<String> files = null;

        try{
            files = new ArrayList<String>();

            ObjectListing result = this.listObjects(bucketName,prefix,"/");

            if(result!=null && result.getObjectSummaries()!=null){
                List<S3ObjectSummary> fileList = result.getObjectSummaries();
                for(S3ObjectSummary summary : fileList){
                    if(!summary.getKey().contains(".csv")){
                        continue;
                    }
                    files.add(extractFileNameFromPath(summary.getKey()));
                }
            }
        } catch(Exception e) {
            e.printStackTrace();
        }

        return files;
    }

    public static String extractFileNameFromPath(String path){
        int idx = path.lastIndexOf('/');
        if(idx>-1){
            return path.substring(idx+1);
        } else {
            return path;
        }
    }
}
